package org.farming.plants;
/**
 * Herb, Plant class
 * @author DEADBEEF
 * @version 0.01a
 * @note The whole class is untested
 * @note Fellstalk and Spiritweed have not been coded
 * @note Goutweed is more than likely bugged and is lacking an interact string
 * @note Wergali stages might be 1 too low
**/
public class Herbs extends Plants
{
    public static enum Herb implements Plants.PlantEnum {
        UNKNOWN     ( -3, "Unknown",     0,  0, 0,     "Unknown",          0,     "Unknown",           "",      false, -1, 0,     ""                  ), 
        NONE        ( -2, "None",        0,  0, 0,     "None",             0,     "None",              "",      false, -1, 0,     "Herb Patch"        ), 
        WEEDS       ( -1, "Weeds",       0,  0, 0,     "Weeds",            6055,  "Weeds",             "",      false, -1, 0,     "Herb Patch"        ), 
        EMPTY       ( 0,  "Empty",       0,  0, 0,     "Empty",            0,     "Empty",             "",      false, -1, 0,     "Herb Patch"        ), 
        GUAM        ( 1,  "Guam Leaf",   9,  5, 5291,  "Guam seed",        199,   "Grimy guam",        "Herbs", true,  1,  249,   "Clean guam"        ), 
        MARRENTILL  ( 2,  "Marrentill",  14, 5, 5292,  "Marrentill seed",  201,   "Grimy marrentill",  "Herbs", true,  5,  251,   "Clean marrentill"  ), 
        TARROMIN    ( 3,  "Tarromin",    19, 5, 5293,  "Tarromin seed",    203,   "Grimy tarromin",    "Herbs", true,  11, 253,   "Clean tarromin"    ), 
        HARRALANDER ( 4,  "Harralander", 26, 5, 5294,  "Harralander seed", 205,   "Grimy harralander", "Herbs", true,  20, 255,   "Clean harralander" ),
        RANARR      ( 5,  "Rannar",      32, 5, 5295,  "Ranarr seed",      207,   "Grimy ranarr",      "Herbs", true,  25, 257,   "Clean ranarr"      ), 
        TOADFLAX    ( 6,  "Toadflax",    38, 5, 5296,  "Toadflax seed",    3049,  "Grimy toadflax",    "Herbs", true,  30, 2998,  "Clean toadflax"    ), 
        IRIT        ( 7,  "Irit",        44, 5, 5297,  "Irit seed",        209,   "Grimy irit",        "Herbs", true,  40, 259,   "Clean irit"        ),
        AVANTOE     ( 8,  "Avantoe",     50, 5, 5298,  "Avantoe seed",     211,   "Grimy avantoe",     "Herbs", true,  48, 261,   "Clean avantoe"     ),
        WERGALI     ( 9,  "Wergali",     46, 5, 14870, "Wergali seed",     14836, "Grimy wergali",     "Herbs", true,  41, 14854, "Clean wergali"     ), 
        KWUARM      ( 10, "Kwuarm",      56, 5, 5299,  "Kwuarm seed",      213,   "Grimy kwuarm",      "Herbs", true,  54, 263,   "Clean kwuarm"      ),
        SNAPDRAGON  ( 11, "Snapdragon",  62, 5, 5300,  "Snapdragon seed",  3051,  "Grimy snapdragon",  "Herbs", true,  59, 3000,  "Clean snapdragon"  ),
        CADANTINE   ( 12, "Cadantine",   67, 5, 5301,  "Cadantine seed",   215,   "Grimy cadantine",   "Herbs", true,  65, 265,   "Clean cadantine"   ),
        LANTADYME   ( 13, "Lantadyme",   73, 5, 5302,  "Lantadyme seed",   2485,  "Grimy lantadyme",   "Herbs", true,  67, 2481,  "Clean lantadyme"   ), 
        DWARF_WEED  ( 14, "Dwarf Weed",  79, 5, 5303,  "Dwarf weed seed",  217,   "Grimy dwarf weed",  "Herbs", true,  70, 267,   "Clean dwarf weed"  ),
        TORSTOL     ( 15, "Torstol",     85, 5, 5304,  "Torstol seed",     219,   "Grimy torstol",     "Herbs", true,  75, 269,   "Clean torstol"     ), 
        FELLSTALK   ( 16, "Fellstalk",   91, 5, 21621, "Fellstalk seed",   21626, "Grimy fellstalk",   "Herbs", true,  91, 21624, "Clean fellstalk"   ), //UNCODED
        SPIRIT_WEED ( 17, "Spirit Weed", 36, 5, 12176, "Spirit weed seed", 12174, "Grimy spirit weed", "Herbs", true,  35, 12172, "Clean spirit weed" ), //UNCODED
        GOUTWEED    ( 18, "Goutweed",    29, 4, 6311,  "Gout tuber",       3261,  "Goutweed",          "",      false, -1, 0,     ""                  ); //UNTESTED itemID, could be 4182, stages uncoded
        
        private final int id, level, stages, seedId, itemId, cleanLevel, cleanItemId;   
        private final String seedString, itemString, interactString, cleanItemString, name;   
        private final boolean canNote;   
           
        /**
         * Herb Enum
         * Interface params
         * @param id Our unique id and offset for the plant
         * @param name The reference for this plant which we can display to the user
         * @param level The farming level required to plant
         * @param stages How many growth stages the plant has (from first planted to harvestable inclusive)
         * @param seedId, Item id of the seed
         * @param seedString, Item string of the seed
         * @param itemId, Item id of the harvested plant
         * @param itemString, Item string of the harvested plant
         * @param interactString, String of the plant when grown
         * @param canNote, Whether the leprechaun can note this plant (noted item id's are +1 of the regular id)
         * Local params
         * @param cleanLevel, Level required to clean the herb, -1 if herb cannot be cleaned
         * @param cleanItemId, Item id of the cleaned herb, 0 if there herb cannot be cleaned
         * @param cleanItemString, String of the plant when grown
        **/
        Herb(
            int id, 
            String name,
            int level, 
            int stages, 
            int seedId, 
            String seedString, 
            int itemId, 
            String itemString, 
            String interactString, 
            boolean canNote,
            int cleanLevel,
            int cleanItemId,
            String cleanItemString
        ) {
            this.id              = id;
            this.name            = name;
            this.level           = level;
            this.stages          = stages;
            this.seedId          = seedId;
            this.itemId          = itemId;
            this.seedString      = seedString;
            this.itemString      = itemString;
            this.interactString  = interactString;
            this.canNote         = canNote;
            this.cleanLevel      = cleanLevel;
            this.cleanItemId     = cleanItemId;
            this.cleanItemString = cleanItemString;
        }
        //Interface methods
        public int id()                 {return id;}
        public int level()              {return level;}
        public int stages()             {return stages;}
        public int seedId()             {return seedId;}
        public int itemId()             {return itemId;}
        public String seedString()      {return seedString;}
        public String itemString()      {return itemString;}
        public String interactString()  {return interactString;}
        public boolean canNote()        {return canNote;}
        public int noteId()             {return canNote?(itemId+1):itemId;}
        public String toString()        {return name;}
        //Local methods
        public boolean canClean()       {return cleanLevel!=-1;}
        public int cleanLevel()         {return cleanLevel;}
        public int cleanItemId()        {return cleanItemId;}
        public String cleanItemString() {return cleanItemString;}
        
    }

    /**
     * This was designed to be a static method, however static and abstract don't mix so this will have to do
     * 
     * @param bits The byte for the herb patch we want the state for
     * @return The calculated state enum
    **/
    public State getState(int bits)
    {
        bits = bits&255;//Cleanse
        int state = (bits>>7)&1;
        if(bits>=0xAA&&bits<=0xAC){                         return State.DEAD;
        }else{
            Herb p = getPlant(bits);
            if(p==Herb.GOUTWEED){//Goutweed special case
                if(bits>=0xC4&&bits<=0xC5){                 return State.READY;
                }else if(bits>=0xC6&&bits<=0xC8){           return State.DISEASED;
                }else if(bits>=0xC9&&bits<=0xCB){           return State.DEAD;
                }else if(bits>=0xC0&&bits<=0xC3){           return State.GROWING;
                }else{                                      return State.UNKNOWN;}
            }else if(p==Herb.EMPTY||p==Herb.WEEDS){         return State.EMPTY;
            }else if(state==0x00){
                if(getStagePlant(p, bits&127)>=p.stages()){ return State.READY;     //>= changed from == due to issue submission
                }else{                                      return State.GROWING;}
            }else if(state==0x01){                          return State.DISEASED;
            }else{                                          return State.UNKNOWN;}
        }
    }
    
    /**
     * This was designed to be a static method, however static and abstract don't mix so this will have to do
     * 
     * @param bits The byte for the herb patch we want the plant for
     * @return The calculated plant enum
    **/
    public Herb getPlant(int bits)
    {
        bits = bits&255;//Cleanse
        int stateBits = (bits&128)>>7;//Get 8th bit
        int plantBits = bits&127;//Clear 8th bit
        if(bits>=0xAA&&bits<=0xAC){                                     return Herb.NONE;//Dead, can't id plant
        }else if(bits>=0xC0&&bits<=0xCB){                               return Herb.GOUTWEED;
        }else if((stateBits==0)&&((plantBits==0x03))){                  return Herb.EMPTY;
        }else if((stateBits==0)&&(plantBits>=0x00)&&(plantBits<=0x02)){ return Herb.WEEDS;
        }else if((plantBits>=0x04)&&(plantBits<=0x0A)){                 return Herb.GUAM;
        }else if((plantBits>=0x0B)&&(plantBits<=0x11)){                 return Herb.MARRENTILL;
        }else if((plantBits>=0x12)&&(plantBits<=0x18)){                 return Herb.TARROMIN;
        }else if((plantBits>=0x19)&&(plantBits<=0x1F)){                 return Herb.HARRALANDER;
        }else if((plantBits>=0x20)&&(plantBits<=0x26)){                 return Herb.RANARR;
        }else if((plantBits>=0x27)&&(plantBits<=0x2D)){                 return Herb.TOADFLAX;
        }else if((plantBits>=0x2E)&&(plantBits<=0x34)){                 return Herb.IRIT;
        }else if((plantBits>=0x35)&&(plantBits<=0x3B)){                 return Herb.AVANTOE;
        }else if((plantBits>=0x3C)&&(plantBits<=0x42)){                 return Herb.WERGALI;
        }else if((plantBits>=0x44)&&(plantBits<=0x4A)){                 return Herb.KWUARM;
        }else if((plantBits>=0x4B)&&(plantBits<=0x51)){                 return Herb.SNAPDRAGON;
        }else if((plantBits>=0x52)&&(plantBits<=0x58)){                 return Herb.CADANTINE;
        }else if((plantBits>=0x59)&&(plantBits<=0x5F)){                 return Herb.LANTADYME;
        }else if((plantBits>=0x60)&&(plantBits<=0x66)){                 return Herb.DWARF_WEED;
        }else if((plantBits>=0x67)&&(plantBits<=0x6D)){                 return Herb.TORSTOL;
        }else{                                                          return Herb.UNKNOWN;}
    }
    
    /**
     * This was designed to be a static method, however static and abstract don't mix so this will have to do
     * 
     * @param bits The byte for the herb patch we want the stage for
     * @return The calculated stage
    **/
    public int getStage(int bits)
    {
        bits = bits&255;//Cleanse
        int plantBits = bits&127;
        return getStagePlant(getPlant(bits), plantBits);
    }
    private int getStagePlant(Herb plant, int plantBits)
    {
        int rtn = 0;
        switch(plant)
        {
            case EMPTY:
            case WEEDS:
            case UNKNOWN:
                                  rtn = 0;
            case GOUTWEED:
                                  rtn = plantBits-191;
            default:
                if(plant.id()<9){ rtn = plantBits-(7*plant.id())+4;
                }else{            rtn = plantBits-(7*plant.id())+3;}
        }
        return (rtn>plant.stages())?plant.stages():rtn;
    }
}
/*
## Herb
    (needs testing and refining)
    format: sppp pppp
    - plant types and growth states (p bits):
    -- 0x00 - 0x03: layers of weeds removed (0x00 meaning no weeds removed, 0x03 meaning all weeds removed), iff both state bits are 0
    -- 0x04 - 0x0a: guam 
    -- 0x0b - 0x11: marrentill
    -- 0x12 - 0x18: tarromin
    -- 0x19 - 0x1f: harralander
    -- 0x20 - 0x26: ranarr
    -- 0x27 - 0x2d: toadflax
    -- 0x2e - 0x34: irit
    -- 0x35 - 0x3b: avantoe
    -- 0x3c - 0x42: wergali
    -- 0x44 - 0x4a: kwuarm
    -- 0x4b - 0x51: snapdragon
    -- 0x52 - 0x58: cadantine
    -- 0x59 - 0x5f: lantadyme
    -- 0x60 - 0x66: dwarf weed
    -- 0x67 - 0x6d: torstol
    -- 0xc0 - 0xcb: goutweed (0xc4/c5 fully grown, 0xc6 - 0xc8 diseased, 0xc9 - 0xcb dead), Full Byte
    -- 0xaa - 0xac: dead herb (depending on growth stage), Full Byte
    - states (s bit):
    -- 0x00: growing
    -- 0x01: diseased

    locations:
    - falador, bits 0-7 of 515
    - catherby, bits 8-15 of 515
    - ardougne, bits 16-23 of 515
    - port phasmatys, bits 24-31 of 515
    - trollheim, bits 0-7 of 830
*/